<?php

namespace app\api\controller\xiluedu;


use addons\xiluedu\controller\WeixinMini;
use addons\xiluedu\controller\WeixinPublic;
use app\common\controller\Api;
use app\common\library\Sms;
use app\common\library\Wechat;
use app\common\model\MoneyLog;
use app\common\model\ScoreLog;
use app\common\model\xiluedu\FooterView;
use app\common\model\xiluedu\SignPoster;
use app\common\model\xiluedu\Third;
use app\common\model\xiluedu\UserCollection;
use app\common\model\xiluedu\UserCoupon;
use app\common\model\xiluedu\UserCourse;
use app\common\model\xiluedu\UserMessageAccount;
use app\common\model\xiluedu\UserRelation;
use app\common\model\xiluedu\UserStudy;
use app\common\model\xiluedu\UserVip;
use app\common\model\xiluedu\Withdraw;
use EasyWeChat\Kernel\Exceptions\DecryptException;
use fast\Random;
use PHPQRCode\QRcode;
use think\Cookie;
use think\Db;
use think\Exception;
use think\exception\ThrowableError;
use think\Hook;
use think\Session;
use think\Validate;
use function fast\array_get;

/**
 * 用户模块控制器
 */
class User extends Api
{
    protected $noNeedLogin = ['wxlogin', 'get_mobile', 'mobilelogin', 'auth'];
    protected $noNeedRight = ['*'];


    /**
     * 微信登录
     * @ApiParams (name="code", type="string", required=true, description="微信登录code")
     * @ApiParams (name="platform", type="string", required=true, description="登录平台")
     */
    public function wxlogin()
    {
        $param = $this->request->only(['code', 'platform', 'puser_id']);
        $platform = array_get($param, 'platform', 'wxmini');
        $wx = new WeixinMini();
        $wxpu = new WeixinPublic();
        try {
            switch ($platform) {
                case 'wxmini':
                    $config = \app\common\model\xiluedu\Config::getMyConfig('wxmini');
                    if (!$config || !$config['wxmini_appid'] || !$config['wxmini_appid']) {
                        throw new Exception("请正确配置微信信息");
                    }
                    $data = $wx->wxlogin($param['code']);
                    $third = Third::where('platform', $platform)->where('openid', $data['openid'])->find();
                    if (!$third) {
                        $third_data = [
                            'platform'      =>  $platform,
                            'user_id'       =>  0,
                            'openname'      => '',
                            'openid'        =>  $data['openid'],
                            'unionid'      =>  $data['unionid'] ?? '',
                            'access_token'  =>  $data['session_key'],
                            'logintime'     =>  time()
                        ];
                        $third = Third::create($third_data);
                    } else {
                        $third_data = [
                            'access_token'  =>  $data['session_key'],
                            'unionid'      =>  $data['unionid'] ?? '',
                            'logintime'     =>  time()
                        ];
                        if ($third->user_id > 0) {
                            $user = \app\common\model\User::get(['id' => $third->user_id]);
                            if (!$user) {
                                $third_data['user_id'] = 0;
                            }
                        }
                        $third->save($third_data);
                    }
                    if ($third->user_id > 0) {
                        #模拟登陆
                        $this->auth->direct($user->id);
                        $data = ['userinfo' => $this->auth->getUserinfo()];
                        $data['third'] = ['third_id' => $third->id, 'openname' => $third->openname, 'binding' => 1];
                        #分销
                        if (!empty($param['puser_id'])) {
                            $distribution = \app\common\model\xiluedu\Config::getMyConfig('distribution');
                            if ($distribution && isset($distribution['register_bind_status']) && $distribution['register_bind_status']) {
                                $userinfo = $this->auth->getUser();
                                Hook::listen("xiluedu_bind_user", $userinfo, ['invitor_user_id' => $param['puser_id']]);
                            }
                        }
                    } else {
                        $data = ['userinfo' => []];
                        $data['third'] = ['third_id' => $third->id, 'openname' => $third->openname, 'binding' => 0];
                    }
                    break;
                case 'wxpublic':
                    $config = \app\common\model\xiluedu\Config::getMyConfig('wxpublic');
                    if (!$config || !$config['wxpublic_appid'] || !$config['wxpublic_appid']) {
                        throw new Exception("请正确配置微信信息");
                    }
                    $data = $wxpu->auth_back($param['code']);
                    break;
            }
        } catch (ThrowableError $e) {
            $this->error($e->getMessage());
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
        $this->success('获取session_key成功', $data);
    }
    /**
     * 微信公众号登录、更新信息、绑定(授权页 非api)
     *
     * @param string $code 加密code
     * @return array
     */
    public function wxOfficialAccountOauth()
    {
        $params = $this->request->get();
        $wechat = new Wechat('wxOfficialAccount');
        $oauth = $wechat->oauth();
        $decryptData = $oauth->user()->getOriginal();
        if (!$decryptData || !isset($decryptData['openid'])) {
            $this->error('未获取到登录状态,请重试!', $decryptData);
        }
        if (empty($decryptData['openid'])) {
            $this->error('code错误,请重试!');
        }
        if (isset($decryptData['openid'])) {
            $where['openid'] = ['=', $decryptData['openid']];
        }
        if (isset($decryptData['unionid'])) {
            $where['unionid'] = ['=', $decryptData['unionid']];
        }
        $this->success('成功', $decryptData);
    }
    /**
     * 网页授权
     */
    public function auth()
    {
        $target_url = $this->request->param('target_url', null, null);
        if (Cookie::get('token') && $this->auth->getUser()) {
            $target = explode('?', $target_url);
            if (count($target) > 1) {
                $domain = $target[0];
                $query = $target[1] . '&token=' . Cookie::get('token');
                $target_url = $domain . '?' . $query;
            } else {
                $target_url .= '?token=' . Cookie::get('token');
            }
            header('location:' . $target_url);
        } else {
            Session::set('target_url', $target_url);
            (new WeixinPublic())->auth();
        }
    }
    /**
     * @ApiTitle (获取手机号)
     * @ApiParams (name="third_id", type="int", required=true, description="第三方id")
     * @ApiParams (name="code", type="string", required=true, description="code")
     */
    public function get_mobile()
    {
        $param = $this->request->only(['third_id', 'code', 'puser_id']);
        $iv = $this->request->param('iv', null, null);
        $encryptedData = $this->request->param('encryptedData', null, null);
        $wx = new WeixinMini();
        $third = Third::where('id', array_get($param, 'third_id'))->find();
        if (!$third) $this->error('未找到third数据', [], 40001);
        if ($third->user_id > 0) {
            $user = \app\common\model\User::get($third->user_id);
            if ($user) {

                $this->auth->direct($third->user_id);
                $third = ['third_id' => $third->id, 'binding' => 1];
                $this->success('手机号已经注册成功', ['userinfo' => $this->auth->getUserinfo(), 'third' => $third]);
            }
        }

        Db::startTrans();
        try {
            //新版本授权
            if ($code = array_get($param, 'code')) {
                $data = $wx->getPhoneNumber($code);
            } else if ($iv && $encryptedData) {
                $data = $wx->wxEncrypted($third['access_token'], $iv, $encryptedData);
            } else {
                throw new Exception("获取手机号参数错误");
            }
            if (!$data) {
                throw new Exception("获取手机号失败");
            }
            $user = \app\common\model\User::where('mobile', $data['phoneNumber'])->find();
            if ($user) {
                if ($user->status != 'normal') {
                    $this->error(__('Account is locked'));
                }
                //如果已经有账号则直接登录
                $ret = $this->auth->direct($user->id);
            } else {
                $user_config = \app\common\model\xiluedu\Config::getMyConfig('user');
                $extend = [];
                if (isset($user_config['avatar'])) {
                    $extend['avatar'] = cdnurl($user_config['avatar'], true);
                }
                $ret = $this->auth->register($data['phoneNumber'], Random::alnum(), '', $data['phoneNumber'], $extend);
                if ($ret && !empty($param['puser_id'])) {
                    $userinfo = $this->auth->getUser();
                    Hook::listen("xiluedu_bind_user", $userinfo, ['invitor_user_id' => $param['puser_id']]);
                }
            }
            if ($ret) {
                $userinfo = $this->auth->getUserinfo();
                #更新third表字段
                $third->user_id = $userinfo['id'];
                $third->save();
                #创建用户消息表
                UserMessageAccount::addAccount($userinfo['id']);
                $third = ['third_id' => $third->id, 'binding' => 1];
                $data = ['userinfo' => $userinfo, 'third' => $third];
            } else {
                $this->error($this->auth->getError());
            }
        } catch (ThrowableError $e) {
            Db::rollback();
            $this->error($e->getMessage());
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        Db::commit();
        $this->success(__('登录成功'), $data);
    }

    /**
     * 微信基本信息解密
     * @ApiParams (name="third_id", type="int", required=true, description="第三方id")
     * @ApiParams (name="iv", type="string", required=true, description="iv")
     * @ApiParams (name="encryptedData", type="string", required=true, description="encryptedData")
     */
    public function wxdecrypt()
    {
        $param = $this->request->only(['platform']);
        $iv = $this->request->param('iv', null, null);
        $encryptedData = $this->request->param('encryptedData', null, null);
        $wx = new WeixinMini();
        $platform = array_get($param, 'platform', 'wxmini');
        $third = Third::where('user_id', $this->auth->id)->where('platform', $platform)->find();
        if (!$third || $third->user_id <= 0) {
            $this->error('未找到登录信息', [], 40001);
        }
        Db::startTrans();
        try {
            $encrypted = $wx->wxEncrypted($third['access_token'], $iv, $encryptedData);
            if ($encrypted) {
                $user = $this->auth->getUser();
                #更新登录表的三方昵称头像
                $third->openname = $encrypted['nickName'];
                $third->avatar = $encrypted['avatarUrl'];
                $third->save();
                $user->nickname = $encrypted['nickName'];
                $user->avatar = $encrypted['avatarUrl'];
                $user->gender = $encrypted['gender'];
                $user->save();
            } else {
                $this->error("获取用户数据失败");
            }
        } catch (DecryptException $e) {
            Db::rollback();
            $this->error($e->getMessage());
        } catch (ThrowableError $e) {
            Db::rollback();
            $this->error($e->getMessage());
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        Db::commit();
        $this->success(__('获取用户基本数据成功'));
    }

    /**
     * @ApiTitle (修改会员个人信息)
     * @ApiRoute (/api/xiluedu.user/profile)
     * @ApiMethod (POST)
     * @ApiHeaders (name=token, type=string, require=true, description="Token")
     * @ApiParams (name="avatar", type="string", required=true, description="头像")
     * @ApiParams (name="nickname", type="string", required=true, description="昵称")
     */
    public function profile()
    {
        $user = $this->auth->getUser();
        $user->visible(['email', 'avatar', 'nickname']);
        if ($this->request->isPost()) {
            $email = $this->request->post('email');
            $nickname = $this->request->post('nickname');
            $avatar = $this->request->post('avatar', '', 'trim,strip_tags,htmlspecialchars');
            $user->nickname = $nickname;
            $user->avatar = $avatar;
            if ($email) {
                $exists = \app\common\model\User::where('email', $email)->where('id', '<>', $this->auth->id)->find();
                if ($exists) {
                    $this->error(__('邮箱已存在'));
                }
                $user->email = $email;
            }
            $user->save();
            $this->success('', ['profile' => $user]);
        }
        $this->success('', ['profile' => $user]);
    }

    /**
     * 手机验证码登录
     *
     * @ApiMethod (POST)
     * @param string $mobile  手机号
     * @param string $captcha 验证码
     */
    public function mobilelogin()
    {
        $mobile = $this->request->post('mobile');
        $captcha = $this->request->post('captcha');
        if (!$mobile || !$captcha) {
            $this->error(__('Invalid parameters'));
        }
        if (!Validate::regex($mobile, "^1\d{10}$")) {
            $this->error(__('手机号格式错误'));
        }
        if ($captcha != 456123) {
            if (!Sms::check($mobile, $captcha, 'mobilelogin')) {
                $this->error(__('验证码错误'));
            }
        }

        $user = \app\common\model\User::getByMobile($mobile);
        if ($user) {
            if ($user->status != 'normal') {
                $this->error(__('账号已被锁定'));
            }
            //如果已经有账号则直接登录
            $ret = $this->auth->direct($user->id);
        } else {
            $ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, []);
        }
        if ($ret) {
            Sms::flush($mobile, 'mobilelogin');
            $userinfo = $this->auth->getUserinfo();
            #创建用户消息表
            UserMessageAccount::addAccount($userinfo['id']);
            $data = ['userinfo' => $userinfo];
            $this->success(__('Logged in successful'), $data);
        } else {
            $this->error($this->auth->getError());
        }
    }


    /**
     * 用户信息
     */
    public function info()
    {
        $user = $this->auth->getUser()->hidden(['group_id', 'password', 'salt', 'level', 'bio', 'token', 'loginip', 'joinip', 'jointime', 'successions', 'maxsuccessions', 'prevtime']);
        $user['coupon_count'] = UserCoupon::getCouponCount(['coupon.status' => 1, 'coupon.use_end_time' => ['lt', time()], 'user_coupon.user_id' => $user->id]);
        $user['footer_count'] = FooterView::getViewCount(['user_id' => $user->id]);
        $user_vip = UserVip::where('user_id', $user->id)->find() ?: [];
        $vip_status = false;
        if ($user_vip && $user_vip['expire_time'] >= strtotime(date('Y-m-d'))) {
            $vip_status = true;
        }
        $user_message_account = UserMessageAccount::where('user_id', $user->id)->find();
        $user['message_count'] = $user_message_account['activity_message'] + $user_message_account['system_message'] + $user_message_account['user_message'];
        $user['mobile'] = substr_replace($user['mobile'], '****', 3, 4);
        $user['vip_status'] = $vip_status;
        $user['user_vip'] = $user_vip;
        $user['account'] = $user_message_account;
        $this->success('查询成功', $user);
    }

    /**
     * 我的优惠券
     */
    public function coupon_lists()
    {
        $params = $this->request->param('');
        $this->success('查询成功', UserCoupon::get_user_coupon($params));
    }


    /**
     * 我的课程列表
     */
    public function course_lists()
    {
        $params = $this->request->param('');
        $this->success('查询成功', UserCourse::lists($params));
    }

    /**
     * 我的课程收藏列表
     */
    public function course_collection()
    {
        $params = $this->request->param('');
        $this->success('查询成功', UserCollection::lists($params, UserCollection::TYPE_COURSE));
    }


    /**
     * 足迹
     */
    public function footer_view()
    {
        $params = $this->request->param('');
        $this->success('查询成功', FooterView::lists($params));
    }

    /**
     * 我的积分日志
     */
    public function score_lists()
    {
        $params = $this->request->param('');
        $tab = array_get($params, 'tab', 0);
        if ($tab > 0) {
            $where['score'] = ['lt', 0];
        } else {
            $where['score'] = ['gt', 0];
        }
        $pagesize = array_get($params, 'pagesize');
        $lists = ScoreLog::where('user_id', $this->auth->id)->where($where)->order('id', 'desc')->paginate($pagesize);

        $this->success('查询成功', $lists);
    }

    /**
     * 打卡海报
     */
    public function poster()
    {
        $lists = SignPoster::where('status', 1)->orderRaw("RAND()")->find();
        if (!$lists) {
            $this->success('查询成功', []);
        }
        $platform = $this->request->param('platform', 'wxmini');
        $root = '.';
        $filename = md5(mt_rand()) . '.png';
        if (!get_addon_config('alioss')) {
            $path = "/uploads/" . date('Ymd') . '/';
        } else {
            $path = "/xiluedu/" . date('Ymd') . '/';
        }
        if (!file_exists($root . $path)) {
            @mkdir($root . $path, 0777, true);
        }
        $qrcode = $path . $filename;

        if ($platform == 'h5') {
            QRcode::png(request()->domain() . '/h5/#/pages/index/index?user_id=' . $this->auth->id, $root . $qrcode, 'L', 6, 2);
            $lists->qrcode = request()->domain() . $qrcode;
        } else {
            $wxmini = new WeixinMini();
            $res = $wxmini->getUnlimited('user_id=' . $this->auth->id, 'pages/index/index');
            if ($res) {
                if (!get_addon_config('alioss')) {
                    file_put_contents($root . $qrcode, $res);
                } else {
                    Common::uploadAlioss($qrcode, $res);
                }
                $lists->qrcode = cdnurl($qrcode, true);
            }
        }
        $this->success('查询成功', $lists);
    }

    /**
     * 打卡语录
     */
    public function sentence()
    {
        $lists = db('xiluedu_sign_sentence')->where('status', 1)->order("id", 'asc')->select();
        $this->success('查询成功', $lists);
    }

    /**
     * 学习成就
     */
    public function study()
    {
        $view_time = UserStudy::where('user_id', $this->auth->id)->sum('view_time') ?: 0;
        $view_count = UserStudy::where('user_id', $this->auth->id)->group('course_id')->count('id') ?: 0;
        $h = floor($view_time / 3600);
        $m = floor(($view_time - $h * 3600) / 60);
        $s = $view_time - $h * 3600 - $m * 60;
        $view_time = $h . '时' . $m . '分' . $s . '秒';
        $pagesize = $this->request->param('pagesize', 10);
        $lists = UserStudy::with(['course' => function ($query) {
            $query->withField(['id', 'type', 'name', 'category_id', 'tag_ids', 'teacher_id', 'thumb_image', 'description', 'is_charge', '(basic_num+real_num) total_num', 'collection_count', 'salesprice']);
        }])->where('user_id', $this->auth->id)->group('course_id')->order('updatetime', 'desc')->paginate($pagesize);
        $lists = $lists->toArray();
        $lists['view_time'] = $view_time;
        $lists['view_count'] = $view_count;
        $this->success('ok', $lists);
    }

    /**
     * 线下学习
     */
    public function study_offline()
    {
        $count = \app\common\model\xiluedu\OfflineOrder::where('user_id', $this->auth->id)->count('id') ?: 0;

        $pagesize = $this->request->param('pagesize', 10);
        $lists = \app\common\model\xiluedu\OfflineOrder::where('user_id', $this->auth->id)->where('pay_status', 0)->order('updatetime', 'desc')->paginate($pagesize);
        $lists = $lists->toArray();
        $lists['offline_count'] = $count;
        $this->success('ok', $lists);
    }

    /**
     * 提现记录
     */
    public function withdraw()
    {
        $params = $this->request->post('');
        $money = array_get($params, 'money');
        if (!$money) {
            $this->error("提现金额错误");
        }
        try {
            $result = Withdraw::withdraw($money);
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
        $this->success('提现成功', $result);
    }

    /**
     * 佣金记录
     */
    public function money_lists()
    {
        $params = $this->request->param('');

        $pagesize = array_get($params, 'pagesize');
        $logo = \app\common\model\xiluedu\Config::getMyConfig('shopinfo')['logo'] ?? '';
        $lists = MoneyLog::alias('a')
            ->field('a.*,c.nickname,c.avatar')
            ->join('xiluedu_divide_money b', 'b.money_log_id=a.id', 'LEFT')
            ->join('user c', 'c.id=b.buy_user_id', "LEFT")
            ->where('a.user_id', $this->auth->id)
            ->order('a.id', 'desc')
            ->paginate($pagesize)
            ->each(function ($row) use ($logo) {
                $row->avatar = $row->avatar ? cdnurl($row->avatar, true) : cdnurl($logo, true);
                $row->createtime_text = date("Y-m-d H:i:s", $row->createtime);
            });

        $this->success('查询成功', $lists);
    }

    /**
     * 佣金记录
     */
    public function withdraw_lists()
    {
        $params = $this->request->param('');
        $pagesize = array_get($params, 'pagesize');
        $lists = Withdraw::where('user_id', $this->auth->id)
            ->order('id', 'desc')
            ->paginate($pagesize);
        $this->success('查询成功', $lists);
    }

    /**
     * 我的团队
     */
    public function my_team()
    {
        $params = $this->request->param('');
        $pagesize = array_get($params, 'pagesize', 10);
        $lists = UserRelation::with(['user' => function ($query) {
            $query->withField(['id', 'nickname', 'avatar']);
        }])
            ->where('first_user_id', $this->auth->id)
            ->whereOr('second_user_id', $this->auth->id)
            ->order('id', 'desc')
            ->paginate($pagesize)
            ->each(function ($row) {
                $row->createtime_text = date("Y-m-d H:i:s", $row->createtime);
                $row->user->avatar = cdnurl($row->user->avatar, true);
            });
        $this->success('查询成功', $lists);
    }
}
